﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JSTT.IPC
{

    public class PipeEventArgs : EventArgs
    {
        private byte[] pipeDatas;

        public PipeEventArgs(byte[] datas) : base()
        {
            pipeDatas = new byte[datas.Length];
            //Array.ConstrainedCopy();
            Buffer.BlockCopy(datas,0,pipeDatas,0,datas.Length);
        }

        public byte[] PipeDatas
        {
            get
            {
                return pipeDatas;
                
            }
        }
    }

    public delegate void PipeReceiveDelegate(object o, PipeEventArgs arg);

    /// <summary>
    /// Pipe 服务器，监听并读取数据
    /// </summary>
    public class NamedPipeListenServer
    {
        List<NamedPipeServerStream> _serverPool = new List<NamedPipeServerStream>();
        private string _pipName = "JSTT_PIPE";

        public event PipeReceiveDelegate pipeReceiveEvent;

        public NamedPipeListenServer(string pipeName)
        {
            _pipName = pipeName;
        }

        /// <summary>
        /// 创建一个NamedPipeServerStream
        /// </summary>
        /// <returns></returns>
        protected NamedPipeServerStream CreateNamedPipeServerStream()
        {
            NamedPipeServerStream nps = new NamedPipeServerStream(_pipName,PipeDirection.InOut,10);
            _serverPool.Add(nps);
            return nps;
        }

        /// <summary>
        /// 销毁Pipe
        /// </summary>
        /// <param name="npss"></param>
        protected void DistroyObject(NamedPipeServerStream npss)
        {
            npss.Close();
            if (_serverPool.Contains(npss))
            {
                _serverPool.Remove(npss);
            }
        }

        /// <summary>
        /// 处理消息
        /// </summary>
        /// <param name="str"></param>
        /// <param name="pipeServer"></param>
        protected virtual void OnPipeReceiveMessage(byte[] datas)
        {
            if (pipeReceiveEvent != null)
            {
                PipeEventArgs pea = new PipeEventArgs(datas);
                pipeReceiveEvent(this, pea);
            }
        }


        /// <summary>
        /// 启动服务器
        /// </summary>
        public void Run()
        {
            using (NamedPipeServerStream pipeServer = CreateNamedPipeServerStream())
            {
                pipeServer.WaitForConnection();
                //Action act = new Action(Run);
                //act.BeginInvoke(null, null);

                try
                {
                    bool isRun = true;
                    while (isRun)
                    {
                        //StreamReader sr = new StreamReader(pipeServer);
                        List<Byte[]> bufferList =new List<byte[]>();
                        
                        while (pipeServer.CanRead )
                        {
                            byte[] buffer = new byte[1024];
                            pipeServer.Read(buffer, 0, 1024);
                            bufferList.Add(buffer);
                            //char[] buffer = new char[sr.BaseStream.Length];
                            //if (sr.Read(buffer, 0, (int) sr.BaseStream.Length) > 0)
                            //{
                            //    OnPipeReceiveMessage(buffer);
                            //}

                            if (!pipeServer.IsConnected)
                            {
                                isRun = false;
                                break;
                            }
                        }
                        if (bufferList.Count > 0)
                        {
                            int bufferAllLength = 0;
                            bufferList.ForEach(t => bufferAllLength += t.Length);
                            byte[] bufferAll = new byte[bufferAllLength];
                            int iIndex = 0;
                            foreach (byte[] buffer in bufferList)
                            {
                                Array.Copy(buffer, 0, bufferAll, iIndex, buffer.Length);
                                iIndex += buffer.Length;
                            }
                            OnPipeReceiveMessage(bufferAll);
                        }
                        Thread.Sleep(3);
                    }
                }
                catch (IOException e)
                {
                    throw (e);
                }
                finally
                {
                    DistroyObject(pipeServer);
                }
            }
        }


        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            for (int i = 0; i < _serverPool.Count; i++)
            {
                var item = _serverPool[i];

                DistroyObject(item);
            }
        }

    }



    public class NamedPipeClient : IDisposable
    {
        string _serverName;
        string _pipName;
        NamedPipeClientStream _pipeClient;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serverName">服务器地址</param>
        /// <param name="pipName">管道名称</param>
        public NamedPipeClient(string serverName, string pipName)
        {
            _serverName = serverName;
            _pipName = pipName;

            _pipeClient = new NamedPipeClientStream(serverName, pipName, PipeDirection.InOut);

        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool SendMessage(byte[] datas)
        {
            if (!_pipeClient.IsConnected)
            {
                _pipeClient.Connect(10000);
            }

            try
            {
                StreamWriter sw = new StreamWriter(_pipeClient);
                char[] chars = new char[datas.Length/sizeof (char)];
                System.Buffer.BlockCopy(datas, 0, chars, 0, datas.Length);

                sw.Write(chars);

                sw.Flush();
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
            
        }

        #region IDisposable 成员

        bool _disposed = false;
        public void Dispose()
        {
            if (!_disposed && _pipeClient != null)
            {
                _pipeClient.Dispose();
                _disposed = true;
            }
        }

        #endregion
    }

}
